#include "ResultConverter.h"
#include "alignerOutput.h"

ResultConverter::~ResultConverter() {};

unsigned int* ResultConverter::getPos() {
	unsigned int* pos = new unsigned int[saResult->numAlignment()];
	unsigned long k = 0;
	for(int i = 0; i < saResult->numSA; i++) {
		for(int j = (saResult->getSA(i)).y; j <= (saResult->getSA(i)).z; j++) {
			pos[k] = saIndex[j];
			k += 1;
		}
	}
	return pos;
}

char* ResultConverter::getQscore() {
	char* qscore = new char[_numAlignment*_readLength];
	unsigned long k = 0;
	unsigned long qid = 0;

	for(int i = 0; i < saResult->numSA; i++) {
		for(int j = (saResult->getSA(i)).y; j <= (saResult->getSA(i)).z; j++) {
			qid = getQid(saResult->getSA(i));
			memcpy(qscore + k*_readLength, 
				querySet->qscore + qid*_readLength, 
				sizeof(char)*_readLength);
			k += 1;
		}
	}
	
	return qscore;
}


unsigned long ResultConverter::getQid(const uint3 sa) {
	unsigned long qid;
	if(!(querySet->isTwoStrand)) {
		qid = sa.x;
	} else {
		qid = (sa.x >= _numQuery/2) ? (sa.x - _numQuery/2) : sa.x;
	}
	return qid;
}

char* ResultConverter::getStrand() {
	char* strand = new char[_numAlignment];
	
	//single strand, all positive strand
	if(!(querySet->isTwoStrand)) {
		for(unsigned long i = 0; i < _numAlignment; i++) {
			strand[i] = '+';
		}
		return strand;
	}

	//double strands
	unsigned long k = 0;
	for(int i = 0; i < saResult->numSA; i++) {
		for(int j = (saResult->getSA(i)).y; j <= (saResult->getSA(i)).z; j++) {
			if((saResult->getSA(i)).x < _numQuery/2) {
				strand[k] = '+';
			} else {
				strand[k] = '-';
			}	
		
			k += 1;	
		}
	}
	return strand;
}


void ResultConverter::mismatchSingle(uchar2 &offset, char2 &sub, 
					const char* read, const unsigned long pos) {

	int numMis = 0;
	int i = 0;
	sub.x = sub.y = -1;
	unsigned char misPos[2];
	for(int i = 0; i < _readLength; i++) {
		if(read[i] != (ref->base)[pos + i]) {
			if(numMis > 2) {
				cout << "ERROR@ResultConverter::mismatchSingle: ";
				cout << "There are more than two mismatches!" << endl;
				exit(-1);
			}

			misPos[numMis] = i;
			numMis += 1;
		}
	}

	if(numMis == 1) {
		offset.x = misPos[0];
		sub.x = read[offset.x];
	} else if(numMis == 2) {
		offset.x = misPos[0];
		sub.x = read[offset.x];
		offset.y = misPos[1];
		sub.y = read[offset.y];	
	}
}


void ResultConverter::getMismatch(uchar2 *&offset, char2 *&sub, const char* strand) {
	offset = new uchar2[_numAlignment];
	sub = new char2[_numAlignment];
	unsigned long k, pos, qid;
	char* read = new char[_readLength];

	k = 0;
	for(int i = 0; i < saResult->numSA; i++) {
		for(int j = (saResult->getSA(i)).y; j <= (saResult->getSA(i)).z; j++) {
			pos = saIndex[j];
			qid = getQid(saResult->getSA(i));
			memcpy(read, (querySet->read) + _readLength*qid, 
				sizeof(char)*_readLength);
			if(strand[k] == '-') {
				reverse_complement(read, read, _readLength);
			}
			
			mismatchSingle(offset[k], sub[k], read, pos);		

			k += 1;
		}
	}
	
	delete[] read;
}

int* ResultConverter::getHit() {
	int* hit = new int[saResult->numAlignment()];
	unsigned long k = 0;
	uint3 sa;
	int saSize;

	for(int i = 0; i < saResult->numSA; i++) {
		sa = saResult->getSA(i);
		saSize = sa.z - sa.y + 1;
		for(int j = sa.y; j <= sa.z; j++) {
			hit[k] = saSize;
			k += 1;
		}
	}

	return hit;
}

void ResultConverter::output_2bwt(string fileName) {

}


